package com.wsoft.oss.controller;

import com.wsoft.constant.CommonConstant;
import com.wsoft.oss.entity.OssFileEntity;
import com.wsoft.oss.manager.OssFileManager;
import com.wsoft.oss.query.MergePartQuery;
import com.wsoft.oss.query.PartUploadQuery;
import com.wsoft.oss.query.SecondUploadQuery;
import com.wsoft.oss.service.IOssFileService;
import com.wsoft.oss.service.IOssService;
import com.wsoft.oss.vo.FileUploadVO;
import com.wsoft.response.ResponseResult;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.net.URLEncoder;
import java.util.Map;

/**
 *  前端控制器
 * @author z001
 * @since 2024年09月26日 15:17:53
 */
@RestController
@Tag(name = "oss附件")
@RequestMapping("/oss/file")
public class OssFileController {

    @Resource
    private IOssFileService ossFileService;
    @Resource
    private IOssService ossService;
    @Resource
    private OssFileManager ossFileManager;
    @Value("${jwt.tokenHeader}")
    private String tokenHeader;
    @Value("${jwt.tokenHead}")
    private String tokenHead;

    @Operation(summary = "校验文件md5", description = "校验文件md5")
    @GetMapping("/check")
    public ResponseResult checkFileByMd5(@RequestParam(value = "md5") String md5,
                                         @RequestParam(value = "fileSize") Integer fileSize){
        return ResponseResult.success(ossFileService.checkFileByMd5(md5,fileSize));
    }

    @Operation(summary = "秒传", description = "秒传")
    @PostMapping("/secondUpload")
    public ResponseResult secondUpload(@RequestBody SecondUploadQuery query) throws Exception {
        return ResponseResult.success(ossService.secondUpload(query));
    }

    @Operation(summary = "直传", description = "直传")
    @PostMapping("/upload")
    public ResponseResult upload(@RequestParam("file") MultipartFile[] multipartFileList,
                                 @RequestParam("bucketType")  Integer bucketType) throws Exception {
        return ResponseResult.success( ossService.uploadList(multipartFileList,bucketType));
    }

    @Operation(summary = "分片上传", description = "分片上传")
    @PostMapping("/uploadPart")
    public ResponseResult uploadPart(@RequestParam("filePart") MultipartFile filePart,
                                     @RequestParam("bucketType")  Integer bucketType,
                                     @RequestParam("md5")  String md5,
                                     @RequestParam("fileName") String fileName,
                                     @RequestParam("uploadPartCount")  Integer uploadPartCount) throws Exception {
        ossService.uploadPart(new PartUploadQuery(md5,bucketType,uploadPartCount,filePart,fileName));
        return ResponseResult.success("上传成功");
    }

    @Operation(summary = "合并分片", description = "合并分片")
    @PostMapping("/mergePart")
    public ResponseResult mergePart(@RequestBody MergePartQuery uploadQuery) throws Exception {
        FileUploadVO vo = ossService.mergePart(uploadQuery);
        return ResponseResult.success(vo);
    }

    @Operation(summary = "前端-删除文件", description = "前端-删除文件")
    @GetMapping("/delete")
    public ResponseResult delete(@RequestParam(value = "id") Long fileId) throws Exception {
        return ResponseResult.success(ossService.deleteFile(fileId));
    }

    // ####################################################################

    @Operation(summary = "下载文件", description = "下载文件")
    @GetMapping("/download")
    public ResponseEntity download(@RequestParam("id") Long id,
                              @RequestParam(value = "picType",required = false) Integer picType,
                              @RequestParam(value = "sessionId",required = false) String sessionId,
                                   HttpServletRequest request) throws Exception{

        Map<String, Object> map = ossFileService.get(id,picType,sessionId);

        // 设置响应头
        HttpHeaders headers = new HttpHeaders();
        headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + URLEncoder.encode(map.get("fileName").toString(), "UTF-8"));
        headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_OCTET_STREAM_VALUE);
        headers.add(HttpHeaders.CACHE_CONTROL, "no-cache, no-store, must-revalidate");
        headers.add(HttpHeaders.PRAGMA, "no-cache");
        headers.add(HttpHeaders.EXPIRES, "0");
        headers.add(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS,HttpHeaders.CONTENT_DISPOSITION);

        return ResponseEntity.ok()
                .headers(headers)
                .body(map.get("stream"));
    }

    @Operation(summary = "分片下载文件", description = "分片下载文件")
    @GetMapping("/downloadPart")
    public ResponseEntity downloadPart(@RequestParam("id") Long id,
                                       @RequestParam(value = "picType",required = false) Integer picType,
                                       HttpServletRequest request, HttpServletResponse response) throws Exception{
        String sessionId = request.getHeader(CommonConstant.SESSION_ID);
        String range = request.getHeader(CommonConstant.RANGE);
        OssFileEntity fileEntity = ossFileManager.getById(id);

        byte[] bytes = ossFileService.downloadPart(fileEntity,picType,sessionId,range,response);
        InputStreamResource resource = new InputStreamResource(new ByteArrayInputStream(bytes));
        // 设置响应头
        HttpHeaders headers = new HttpHeaders();
        headers.add(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS,HttpHeaders.CONTENT_DISPOSITION);
        headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + URLEncoder.encode(fileEntity.getName(), "UTF-8"));
        headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_OCTET_STREAM_VALUE);
        headers.add(HttpHeaders.CACHE_CONTROL, "no-cache, no-store, must-revalidate");
        headers.add(HttpHeaders.PRAGMA, "no-cache");
        headers.add(HttpHeaders.EXPIRES, "0");
        return ResponseEntity.ok()
                .headers(headers)
                .body(resource);
    }

}
